package com.dong.es.entity;

import com.dong.es.anno.DTOCastAnno;
import com.dong.es.anno.DTOCastAnnos;
import com.dong.es.entity.dtocast.DTOCastMethod;
import com.dong.es.util.ReflectUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Comparator;

/**
 * 类上使用@DTOCastAnnos注解使用查询参数转换功能，使用条件：
 * 需要实现getter方法，严格按照 "get + 属性首字母大写"的形式
 * @description: ES 接收前端参数抽象类
 * @author: 陈瑞东
 * @create: 2022-06-21 09:40
 */
public abstract class EsViewDTO implements Serializable {

    private static final long serialVersionUID = 1463029929732130534L;

    public <T extends EsBaseDTO> T build(T esBaseDTO) {
        try {
            // 获取上传参数对象的class
            Class<?> clazz = this.getClass();
            // 获取转换注解数组
            DTOCastAnnos annotation = clazz.getAnnotation(DTOCastAnnos.class);
            if (annotation != null) {
                // 排序
                DTOCastAnno[] annos = Arrays.stream(annotation.value()).sorted(
                        new Comparator<DTOCastAnno>() {
                            @Override
                            public int compare(DTOCastAnno o1, DTOCastAnno o2) {
                                return new Integer(o1.sort()).compareTo(new Integer(o2.sort()));
                            }
                        }
                ).toArray(DTOCastAnno[]::new);
                // 遍历注解进行转换
                for (DTOCastAnno anno : annos) {
                    // 获取注解中的转换方法
                    Class<? extends DTOCastMethod> methodClass = anno.method();
                    // 获取注解中的字段名称
                    String field = anno.field();
                    // 获取注解中指定的需要获取的值的字段
                    String[] paramFields = anno.paramFields();
                    // 获取注解中指定的需要添加的参数值
                    String[] paramStrs = anno.paramStrs();
                    // 获取是否启用标记
                    boolean enabled = anno.enabled();
                    // 获取是否启用的字段
                    String enabledField = anno.enabledField();

                    // 判断是否启用标记，如果不启用，则跳过本次循环
                    if (!enabled) {
                        continue;
                    }

                    // 判断启用的字段，是否填写，如果填写，则判断值是否为true
                    if (StringUtils.isNotBlank(enabledField)) {
                        // 调用该字段的get方法
                        Object value = ReflectUtils.invokeGetter(this, enabledField);
                        // 判断value的值是否为空，是的话不启用
                        // 判断value的类型是否为布尔类型，如果是的话继续比较，如果不是的话不启用
                        if (value == null || !(value instanceof Boolean)) {
                            continue;
                        }
                        // 如果value的值不为true，则不启用
                        if (!(Boolean)value) {
                            continue;
                        }
                    }

                    // 用于调用转换方法的参数，需要将字段名和获取到的字段值存入，因此 +1
                    int paramsSize = paramStrs.length + paramFields.length;
                    Object[] params = new Object[paramsSize + 1];
                    params[0] = field;
                    // 如果field为空，则不加入参数
                    if (StringUtils.isBlank(field)) {
                        params = new Object[paramsSize];
                    }

                    // 遍历字段名称获取字段值
                    for (int i = 0; i < paramFields.length; i++) {
                        // 获取字段名称
                        String paramField = paramFields[i];

                        // 执行方法Getter方法
                        Object o = ReflectUtils.invokeGetter(this, paramField);

                        int index = i + 1;
                        if (paramsSize == params.length) {
                            index = i;
                        }
                        params[index] = o;
                    }

                    // 遍历字段名称获取字段值
                    for (int i = 0; i < paramStrs.length; i++) {
                        int index = i + paramFields.length + 1;
                        if (paramsSize == params.length) {
                            index = i + paramFields.length;
                        }
                        params[index] = paramStrs[i];
                    }



                    // 创建转换方法的对象
                    DTOCastMethod dtoCastMethod = methodClass.newInstance();
                    // 执行转换方法
                    dtoCastMethod.cast(this, esBaseDTO, params);

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return esBaseDTO;
    }
}
